
/**
 * @file SolverNetAmb.hpp
 * Class to compute the satellite/source phase biases using given ambiguities.
 *
 * @author shjzhang, 2019/07/22
 * all rights reserved by shjzhang
 */

#ifndef GPSTK_SolverNetAmb_HPP
#define GPSTK_SolverNetAmb_HPP

#include "TypeID.hpp"
#include "SatID.hpp"
#include "DataStructures.hpp"
#include "ARMLambda.hpp"
#include "Kruskal.hpp"
#include "ARRound.hpp"
#include "Equation.hpp"
#include "Stats.hpp"
#include "SolverAmb.hpp"
#include "SolverBase.hpp"


namespace gpstk
{
      /**This class solve the receiver and satellite biass using the
       * kruskal algorithm to create a minimum spanning tree, which
       * provide the independent ambiguity datum for ambiguity solution
       * and bias solution.
       *
       * step 1:
       * according to the given sourceSatAmbiData, get all the ambiguity
       * candidate, then create the independent ambiguities
       *
       * step 2:
       * with the independent ambiguities, let's get the bias observables
       * then solve the receiver and satellite bias using the independent
       * biasObs
       * 
       * step 3:
       * substitue the receiver and satellite biass into all the MW observations
       * then all the Nw ambiguities will be biasated, then the lambda 
       * method is used to fix all the potential ambigities
       *
       * step 4:
       * biasate the biasObs, then solve the bias observations again, to get
       * more precise biass.
       *    
       */

   class SolverNetAmb 
   {
   public:

          /** Common constructor.
           *
           * @param useNEU   If true, will compute dLat, dLon, dH coordinates;
           *                 if false (the default), will compute dx, dy, dz.
           */
       SolverNetAmb()
           : firstTime(true), usingBlockWiseLSQ(true), cutDev(0.15),cutSig(0.15),shift(true)
       {
           ambRound.setCutDev(cutDev);
           ambRound.setCutSig(cutSig);
           init();
       };

       virtual SolverNetAmb& setAmbType(TypeID type)
       {
           ambType = type;
           return (*this);
       };


       virtual SolverNetAmb& setUsingBlockWiseLSQ(bool useBWLSQ)
       {
           usingBlockWiseLSQ = useBWLSQ;
           return (*this);
       };

       virtual SolverNetAmb& setCutDev(double dev)
       {
           ambRound.setCutDev(dev);
           return (*this);
       };

       virtual SolverNetAmb& setCutSig(double sig)
       {
           ambRound.setCutSig(sig);
           return (*this);
       };

       virtual int Solve( const CommonTime& epoch,
                          VariableEstDataMap& ambEstData)
          noexcept(false);

       virtual int solveBiasEquations(VariableEstDataMap& ambBiasData);

       virtual void biasConnect();
       virtual void biasShift();

       virtual satValueMap getSatBiasData() const;
       virtual sourceValueMap getSourceBiasData() const;

       virtual VariableEstDataMap getFixedAmbEstData() const;

          /// Returns a string identifying this object.
       virtual std::string getClassName(void) const;

       virtual void init();

          /// Destructor.
       virtual ~SolverNetAmb() {};

   private:

       bool firstTime;

       bool usingBlockWiseLSQ;
       bool shift;

       double cutDev, cutSig;

       CommonTime currEpoch;
       
       TypeID ambType;
       SatID::SatelliteSystem satSys;

       SatID datumSat;

       VariableEstDataMap ambFixedCurr;
       VariableEstDataMap ambFixedLast;

       sourceValueMap sourceBiasData;
       satValueMap satBiasData;

       sourceValueMap oldSourceBiasData;
       satValueMap oldSatBiasData;

       sourceValueMap allOldSourceBiasData;
       satValueMap allOldSatBiasData;

       VariableEstDataMap ambEstDataFixed;

       ARRound ambRound;
       SolverAmb ambSolver;

   }; // End of class 'SolverNetAmb'

      //@}

}  // End of namespace gpstk

#endif   // GPSTK_SolverNetAmb_HPP
